val names= {'a' to 'z' toArray};

println("package org.thewares.collection.test;");
println("object LittleDeques {");
println(" trait LittleDeque[+T] { ");
println("  def ::[S>:T](s:S):LittleDeque[S];");
println("  def tail:LittleDeque[T];");
println("  def head:T;");
println(" }");
println(" sealed abstract class LittleList[+A] extends LittleDeque[A]{");
println("  def ::[S >: A](s:S):LittleList[S];");
println("  def tail:LittleList[A];");
println("  def head:A;");
println("  def length:Int;");
println(" }");
println(" case object LittleList0 extends LittleList[Nothing]{");
println("  def length=0;");
println("  def ::[S](s:S)=LittleList1(s);")
println("  def tail:LittleList[Nothing]=throw new Error;");
println("  def head=throw new Error;");
println(" }");
println(" case class LittleList1[+A](hd:A) extends LittleList[A]{");
println("  def ::[S >: A](s:S):LittleList2[S]= LittleList2(s,this);");
println("  def tail=LittleList0;");
println("  def head:A=hd;");
println("  def length:Int=1;");
println(" }");
for (i <- 2 to 20){
val (pre,here,suc)=(i-1,i,i+1);
println(" case class LittleList"+here+"[+A](hd:A, tl: LittleList"+pre+"[A]) extends LittleList[A]{");
println("  def ::[S >: A](s:S):LittleList"+suc+"[S]= LittleList"+suc+"(s,this);");
println("  def tail:LittleList"+pre+"[A]=tl;");
println("  def head:A=hd;");
println("  def length:Int="+here+";");
println(" }");
}
println(" case class LittleList21[+A](hd:A,tl:LittleList20[A]) extends LittleList[A]{");
println("  def length=21;");
println("  def ::[S](s:S)=throw new Error;")
println("  def tail:LittleList20[A]=tl;");
println("  def head=hd;");
println(" }");


println(" case object EmptyLetter extends LittleDeque[Nothing]{");
println("  def ::[S](s:S):Letter_a[S] = Letter_a(s);");
println("  def tail:LittleDeque[Nothing]=throw new Error;");
println("  def head:Nothing=throw new Error;");
println(" }");
println(" case class Letter_a[+T](a:T) extends LittleDeque[T] { ");
println("  def ::[S>:T](elem:S):LittleDeque[S]=Letter_b(elem,a);");
println("  def tail:LittleDeque[T]=EmptyLetter;");
println("  def head:T=a;");
println(" }");
for (i <- 1 to 20){
val (pre,here,suc,all)=(names(i-1),names(i),names(i+1),names.take(i+1));
println(" case class Letter_"+here+"[+T]("+all.mkString("",":T,",":T")+") extends LittleDeque[T] { ");
println("  def ::[S>:T](elem:S):LittleDeque[S]= Letter_"+suc+"(elem,"+all.mkString(",")+");");
println("  def tail:LittleDeque[T]= Letter_"+pre+" ("+all.drop(1).mkString(",")+");");
println("  def head:T=a;");
println(" }");
}
println(" case class Letter_v[+T](a:T,b:T,c:T,d:T,e:T,f:T,g:T,h:T,i:T,j:T,k:T,l:T,m:T,n:T,o:T,p:T,q:T,r:T,s:T,t:T,u:T,v:T) extends LittleDeque[T] { ");
println("  def ::[S>:T](elem:S):LittleDeque[S]=throw new Error;");
println("  def tail:LittleDeque[T]=Letter_u(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v);");
println("  def head:T=a;");
println(" }");

println(" object EmptyTup extends LittleDeque[Nothing]{");
println("  def ::[S](s:S):Tup1[S] = Tup1(s);");
println("  def tail:LittleDeque[Nothing]=throw new Error;");
println("  def head:Nothing=throw new Error;");
println(" }");
println(" final case class Tup1[+T](_1 :T) extends LittleDeque[T] { ");
println("  final def ::[S>:T](elem:S):LittleDeque[S]=new Tup2(elem, _1);");
println("  final def tail:LittleDeque[T]=EmptyTup;");
println("  final def head:T=_1;");
println(" }");
for (i <- 2 to 20){
val (pre,here,suc,all)=(i-1,i,i+1,{1 to i toList}.map("_"+_));
println(" final class Tup"+here+"[+T]("+all.mkString("",":T, ",":T")+") extends LittleDeque[T] { ");
println("  final def ::[S>:T](elem:S):LittleDeque[S]= new Tup"+suc+"(elem, "+all.mkString(", ")+");");
println("  final def tail:LittleDeque[T]= new Tup"+pre+" ("+all.drop(1).mkString(",")+");");
println("  final def head:T= _1;");
println(" }");
}
println(" final class Tup21[+T](_1:T, _2:T, _3:T, _4:T, _5:T, _6:T, _7:T, _8:T, _9:T, _10:T, _11:T, _12:T, _13:T, _14:T, _15:T, _16:T, _17:T, _18:T, _19:T, _20:T, _21:T) extends LittleDeque[T] { ");
println("  final def ::[S>:T](elem:S):LittleDeque[S]= throw new Error;");
println("  final def tail:LittleDeque[T]= new Tup20 (_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21);");
println("  final def head:T= _1;");
println(" }"); 

println(" case object EmptyA extends LittleDeque[Nothing]{");
println("  def ::[S](s:S):A1[S] = A1{val arr=new Array[S](1);arr(0)=s;arr}");
println("  def tail:LittleDeque[Nothing]=throw new Error;");
println("  def head:Nothing=throw new Error;");
println(" }");
println(" case class A1[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  def ::[S>:T](s:S):A2[S]=A2{val arr=new Array[S](2);arr(0)=s;arr(1)=a(0);arr};");
println("  def tail=EmptyA;");
println("  def head:T=a(0);");
println(" }");
for (i <- 2 to 21){
val (pre,here,suc)=(i-1,i,i+1);
println(" case class A"+here+"[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  def ::[S>:T](s:S):A"+suc+"[S]= A"+suc+"{val arr=new Array[S]("+suc+");arr(0)=s;Array.copy(a,0,arr,1,"+here+"); arr};");
println("  def tail:A"+pre+"[T]= A"+pre+"{val arr=new Array[T]("+pre+");Array.copy(a,1,arr,0,"+pre+");arr}");
println("  def head:T=a(0);");
println(" }");
}
println(" case class A22[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  def ::[S>:T](s:S):LittleDeque[S]=throw new Error;");
println("  def tail:A21[T]= A21{val arr=new Array(21);Array.copy(a,1,arr,0,21);arr}");
println("  def head:T=a(0);");
println(" }");

println(" case object EmptyB extends LittleDeque[Nothing]{");
println("  final def ::[S](s:S):B1[S] = { val arr=new Array[S](1);arr(0)=s;B1(arr)}");
println("  final def tail:LittleDeque[Nothing]=throw new Error;");
println("  final def head:Nothing=throw new Error;");
println(" }");
println(" final case class B1[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  final def ::[S>:T](s:S):B2[S]={val arr=new Array[S](2);arr(0)=s;arr(1)=a(0);B2(arr)};");
println("  final def tail=EmptyB;");
println("  final def head:T=a(0);");
println(" }");
for (i <- 2 to 21){
val (pre,here,suc)=(i-1,i,i+1);
println(" final case class B"+here+"[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  final def ::[S>:T](s:S):B"+suc+"[S]= {val arr=new Array[S]("+suc+");arr(0)=s;Array.copy(a,0,arr,1,"+here+"); B"+suc+"(arr)};");
println("  final def tail:B"+pre+"[T]= {val arr=new Array("+pre+");Array.copy(a,1,arr,0,"+pre+");B"+pre+"(arr)}");
println("  final def head:T=a(0);");
println(" }");
}
println(" final case class B22[+T](a:RandomAccessSeq[T]) extends LittleDeque[T] { ");
println("  final def ::[S>:T](s:S):LittleDeque[S]=throw new Error;");
println("  final def tail:B21[T]= B21{val arr=new Array(21);Array.copy(a,1,arr,0,21);arr}");
println("  final def head:T=a(0);");
println(" }");



println(" } // little deques");
